import BaseView from "../../../Script/Base/BaseView";
import { EBundleType, EResType, EViewType } from "../../../Script/Common/Enum";
import { ISayConfig, TalkModule } from "../../../Script/Common/TalkModule";
import { IBaseSkeData, IGameData, IHospitalData, IHospitalGuestData, IHospitalLevelData, ISelectData, ITalkData, IViewData } from "../../../Script/Interface/IMessage";
import { SceneGame } from "../../../Script/SceneGame";
import AppService from "../../../Script/Service/AppService";
import AudioManager, { EMusicType, ESoundType } from "../../../Script/Util/AudioManager";
import GameUtil from "../../../Script/Util/GameUtil";
import { LoadUtil } from "../../../Script/Util/LoadUtil";
import StorageUtil from "../../../Script/Util/StorageUtil";
import EventID from "../../Common/EventID";
import { GlobalData } from "../../Common/GlobalData";
import Message from "../../Common/Message";
import TaskModule from "../../Common/TaskModule";
import { AdManager } from "../../naodong/ads/AdManager";
import GameUI from "../GameUI";
import TownUI from "../town/TownUI";
import HospitalGroup from "./HospitalGroup";
import HospitalIcon from "./HospitalIcon";
import HospitalTalk from "./HospitalTalk";
import HospitolGuest from "./HospitolGuest";

const { ccclass, property } = cc._decorator;

export const DATA: { name: string, id: number } = { name: '怀旧消除', id: -99 };

export const MAX_GROUP: number = 12;
export const REMOVE_NUM: number = 3;
export const TEMP_NUM: number = 6;
export const MAX_GUEST: number = 4;
export const UNLOCK_NUM: number = 2;

/** 视频类型 */
export enum EVideoType {
    /** 顾客解锁 */
    Unlock = 13,
    /** 直接取货 */
    Pickup,
    /** 清空格子 */
    Clean,
    /** 复活 */
    Revive,
    /** 整理格子 */
    ClearUp,
}

export enum EItemType {
    Fly,
    Item,
    Temp,
    Test,
    Guest,
}

export enum EFlyType {
    Item,
    Progress,
}

export enum EViewName {
    Null = '',
    Revive = 'revive',
    Pause = 'pause',
    Fail = 'fail',
    Success = 'success',
}

export interface ISkeData {
    id: number;
    name: string;
    x: number;
    y: number
}

const VIEW_DATA: IViewData = {
    name: 'HospitalUI',
    type: EViewType.Panel,
    bundle: EBundleType.Game,
    zIndex: 100,
};

@ccclass
export default class HospitalUI extends BaseView {
    public static instance: HospitalUI = null;

    @property({ type: cc.Node, tooltip: "单元组预制体" })
    private itemGroup: cc.Node = null;
    @property({ type: cc.Node, tooltip: "顾客预制体" })
    private itemGuest: cc.Node = null;
    @property({ type: cc.Node, tooltip: "物品预制体" })
    private itemIcon: cc.Node = null;

    @property({ type: cc.Node, tooltip: "弹窗节点" })
    private view: cc.Node = null;
    @property({ type: cc.Node, tooltip: "和刘神医对话层" })
    private talk: cc.Node = null;

    @property({ type: sp.Skeleton, tooltip: "整理动画" })
    private zhengliSke: sp.Skeleton = null;
    @property({ type: sp.Skeleton, tooltip: "整理动画" })
    private guitaiSke: sp.Skeleton = null;

    // @property({ type: cc.Node, tooltip: "组背景节点" })
    // private groupBg: cc.Node = null;
    @property({ type: [cc.Node], tooltip: "货架背景" })
    private groupBgs: cc.Node[] = [];
    @property({ type: cc.Node, tooltip: "组节点" })
    private group: cc.Node = null;
    @property({ type: cc.Node, tooltip: "顾客节点" })
    private guest: cc.Node = null;
    @property({ type: cc.Node, tooltip: "暂存节点" })
    private temp: cc.Node = null;
    @property({ type: cc.Node, tooltip: "飞" })
    private flyItem: cc.Node = null;


    @property({ type: cc.Node, tooltip: "游戏层遮罩" })
    private block: cc.Node = null;

    @property({ type: cc.Node, tooltip: "进度条节点" })
    private proNode: cc.Node = null;
    @property({ type: cc.Node, tooltip: "升级按钮" })
    private btnUpgrade: cc.Node = null;
    @property({ type: cc.Node, tooltip: "升级锤子" })
    private btnChuizi: cc.Node = null;
    @property({ type: cc.Label, tooltip: "称号" })
    private labTitle: cc.Label = null;
    @property({ type: cc.Label, tooltip: "托管倒计时" })
    private labAutoTime: cc.Label = null;

    private curView: EViewName = EViewName.Null;
    private upLevel: { total: number, p: number, kinds: number } = { total: 3000, p: 100, kinds: 13 };
    private autoTime: { add: number } = { add: 30 };

    private groupNodes: cc.Node[] = [];
    private guestNodes: cc.Node[] = [];
    private tempNodes: cc.Node[] = [];

    private gameData: IGameData = null;
    private talkData: ITalkData = null;

    private isGameEnd: boolean = false;
    private hospitalData: IHospitalData = null;
    public get _hospitalData() {
        return this.hospitalData;
    }

    private _data: IHospitalLevelData = null;
    public get data() {
        return this._data;
    }

    protected onLoad() {
        super.onLoad();
        HospitalUI.instance = this;

        // 打开时消除游戏时，埋点上报
        // AdManager.reportLevel(DATA.id, DATA.name, 0);
        AudioManager.instance.playMusic(EMusicType.MusicHospital);

        // 读取存储数据
        this.gameData = StorageUtil.instance.getGameData();
        this.talkData = StorageUtil.instance.getTalkData();
        this.hospitalData = StorageUtil.instance.getHospitalData();

        // 后退一步，冰封聊天
        if (this.talkData.id === 10709) {
            this.talkData.id = 10708;
            TalkModule.updateCheck();
        } else if (this.talkData.id === 10800) {
            TalkModule.updateCheck();
        }

        this.talk.active = this.talkData.id < 10802;
        
        // 初始化称号
        this.setTitle();
        // 初始化柜台
        this.upgradeGuiTai();
        // 游戏初始化
        this.initData();
        this.check();
        // // 计算距上次退出经过x秒
        // this.countPassTime();
    }

    // private countPassTime() {
    //     // 关闭时剩余时间
    //     const remain = this.hospitalData.autoEndTime - this.hospitalData.exitTime;
    //     if (remain > 0) {
    //         const pass = Date.now() - this.hospitalData.autoEndTime;
    //         if (pass > 0) {
    //             console.log('已超过托管时间===>经过:', pass, '------挂机期间走:', Math.floor(pass / 2));
    //         } else {
    //             // 距现在剩余时间
    //             // const temp = -pass;//this.hospitalData.autoEndTime - Date.now();
    //             const real = remain - (-pass);
    //             console.log('没超过托管时间===>经过:', real, '------挂机期间走:', Math.floor(real / 2));
    //         }
    //     }
    // }

    private countAutoTime() {
        const left = Math.floor((this.hospitalData.autoEndTime - Date.now()) / 1000);
        if (left > 0) {
            this.labAutoTime.node.active = true;
            this.labAutoTime.string = left < 10 ? `00:0${left}` : `00:${left}`;
        } else {
            this.labAutoTime.node.active = false;
            this.labAutoTime.string = `00:00`;
        }
    }

    public async check(talk?: ISayConfig) {
        if (!this.talkData || !this.hospitalData || !this.gameData) {
            return;
        }

        this.updateLine(talk);
        this.updateTeacher();
    }

    private async updateLine(talk?: ISayConfig) {
        // 刘神医张嘴/闭嘴
        if (talk) {
            if (talk.name === '刘神医') {
                HospitalTalk.instance.showMouth();
            } else {
                HospitalTalk.instance.hideMouth();
            }
        }

        switch (this.talkData.id) {
            case 10608:
                await GameUtil.sleep(100);
                HospitalTalk.instance?.showCartoon();
                break;
            case 10708:
                await GameUtil.sleep(100);
                HospitalTalk.instance?.playAnimation();
                break;
            case 10711:    // 冰封动画
                await GameUtil.sleep(100);
                HospitalTalk.instance?.bingActive();
                break;
            case 10802:
                this.updateTeacher();
                break;
        }
    }

    private async updateTeacher() {
        if (this.talkData.id === 10802 || this.talkData.id === 10806) {
            switch (this.hospitalData.student) {
                case 0: // 未拜师
                    {
                        await GameUtil.sleep(200);
                        this.showShouTu();  // 拜师弹窗
                    }
                    break;
                case 1: // 已拜师
                case 2: // 拒绝拜师
                case 3: // 拒绝拜师(已出提示: '在御康馆打杂，成为药馆学徒')
                    {
                        if (this.hospitalData.student === 2 && this.gameData.brain >= 55) {
                            this.hospitalData.student = 3;
                            this.showTips();
                        }

                        // 需要达到医馆学徒
                        if (this.hospitalData.id >= 3) {
                            // 先更新任务数据
                            TaskModule.instance.saveData();
                            // 继续流程
                            this.talkData.id = 10900;
                            TalkModule.updateCheck();
                        }
                    }
                    break;
            }
        }
    }

    // 弹出刘神医收徒弹窗
    private isShow: boolean = false;
    public showShouTu() {
        if (this.isShow) {
            return;
        }
        this.isShow = true;
        const data: ISelectData = {
            desc: "御康馆的刘神医打算收你为关门弟子，教授医术",
            success: {
                lab: "欣然接受", // （智商所需：55）
                // isVideo: true,
                callback: () => {
                    // 成为刘神医徒弟
                    this.hospitalData.student = 1;
                    this.talkData.id = 10805;
                    // TalkModule.updateCheck();
                    HospitalTalk.instance.isActive(false);
                }
            },
            fail: {
                lab: "厉声拒绝",
                next: {
                    desc: "哼！没礼貌的小子，不知好歹",
                    fail: {
                        callback: () => {
                            HospitalTalk.instance.playPaiZhuoZi(() => {
                                // 不是刘神医徒弟
                                this.hospitalData.student = 2;
                                SceneGame.instance.removeAllPopView();
                                SceneGame.instance.showToast(cc.v2(0, 0), '情商堪忧，被刘神医逐出御康馆');
                            });
                        }
                    }
                },
            },
            callback: ()=>{
                Message.instance.send(EventID.HIDE_VIEW_CLOSE, { hide: 'top' });
            }
        }
        SceneGame.instance.showPopView("SelectUI", data);
        // 任务数据
        TaskModule.instance.saveData();
    }
    
    // 弹出刘神医收徒弹窗
    public showTips() {
        // TODO 出现提示
        SceneGame.instance.showToast(cc.v2(0, 0), '在御康馆打杂，成为药馆学徒');
    }

    private setTitle() {
        const id = this.hospitalData.id;
        const title = GlobalData.getHospitalConfig(id);
        this.labTitle.string = `${title.name}`;
    }

    private upgradeGuiTai() {
        const groupLv = this.hospitalData.groupLv;
        this.groupBgs.forEach((o, i) => {
            o.active = i === groupLv - 1;
        });
    }

    public curItemId: number = -1;
    private initData() {
        const levelData = { total: this.upLevel.total, col: 3, itemId: [] };
        for (let i = 0; i < this.upLevel.kinds; i++) {
            levelData.itemId.push(i + 1);
        }
        this._data = { total: levelData.total, col: levelData.col, ids: levelData.itemId, counts: [] };

        this.groupNodes.forEach((o) => {
            o.destroy();
        });
        this.guestNodes.forEach((o) => {
            o.destroy();
        });
        this.tempNodes.forEach((o) => {
            o.destroy();
        });

        this.isGameEnd = false;
        this.view.active = false;
        this.block.active = false;
        this.btnChuizi.active = false;
        this.btnUpgrade.active = false;

        this.curItemId = -1;

        this.groupNodes = [];
        this.guestNodes = [];
        this.tempNodes = [];

        this.groupModule();
        this.guestModule();
        this.tempItemsModule();
        this.refreshProgress();
    }

    private groupModule() {
        if (this.hospitalData.cellData.length === 0) {
            // 每种物品个数
            const value = this.data.total / REMOVE_NUM;
            const count = value / this.data.ids.length;
            for (let i = 0; i < this.data.ids.length; i++) {
                const much = Math.ceil(count) * REMOVE_NUM;
                const less = Math.floor(count) * REMOVE_NUM;
                this.data.counts.push(i < value % this.data.ids.length ? much : less);
            }

            // 计算单元深度(每列个数)
            const totalGroup = this.data.col * MAX_GROUP;
            const cellCol = this.data.total / totalGroup;
            for (let i = 0; i < totalGroup; i++) {
                this.setItemData(i, i >= this.data.total % totalGroup ? Math.floor(cellCol) : Math.ceil(cellCol));
            }
        }

        for (let i = 0; i < MAX_GROUP; i++) {
            const node = cc.instantiate(this.itemGroup);
            node.parent = this.group;
            node.getComponent(HospitalGroup).setData(i);
            this.groupNodes.push(node);
        }
    }

    private guestModule() {
        if (this.hospitalData.guestData.length === 0) {
            for (let i = 0; i < MAX_GUEST; i++) {
                const itemId = i < UNLOCK_NUM ? this.getItemIdBySurface() : -1;
                const skeId = Math.floor(Math.random() * 6);
                this.hospitalData.guestData.push({ guestId: i, itemId: itemId, cur: 0, max: 3, isLock: i >= UNLOCK_NUM, skeId: skeId });
            }
        } else {
            // 特殊处理: 会有特殊情况, 存数据的时候正好已完成, 顾客还没走
            this.hospitalData.guestData.forEach((o, i) => {
                if (o.cur >= o.max) {
                    o.cur = 0;
                    o.itemId = this.getItemIdBySurface();
                    o.skeId = Math.floor(Math.random() * 6);
                }
            });
        }

        for (let i = 0; i < this.hospitalData.guestData.length; i++) {
            const guest = this.hospitalData.guestData[i];
            const node = cc.instantiate(this.itemGuest);
            node.parent = this.guest;
            node.getComponent(HospitolGuest).setData(guest);
            this.guestNodes.push(node);
        }
    }

    private tempItemsModule() {
        if (this.hospitalData.tempData.length === 0) {
            for (let i = 0; i < TEMP_NUM; i++) {
                this.hospitalData.tempData.push(-1);
            }
        } else {
            this.checkGameFail();
        }

        // 更新暂存区初始UI
        const posX = [35, 145, 250, 340, 450, 560];
        for (let i = 0; i < this.hospitalData.tempData.length; i++) {
            const node = cc.instantiate(this.itemIcon);
            node.parent = this.temp;
            node.x = posX[i];
            node.getComponent(HospitalIcon).setTempData({ tempId: i, itemId: this.hospitalData.tempData[i] }, -1);
            this.tempNodes.push(node);
        }
    }

    /**
     * 暂存区到顾客气泡
     * @param itemId 
     */
    public tempToGuest(itemId: number) {
        if (this.isGameEnd) {
            return;
        }

        this.hospitalData.tempData.forEach((o, i) => {
            if (o === itemId) {
                const from = this.tempNodes[i];
                this.flyItemIcon(from, itemId);
                this.hospitalData.tempData[i] = -1;
                this.tempNodes[i].getComponent(HospitalIcon).setTempData({ tempId: i, itemId: this.hospitalData.tempData[i] }, -1);
            }
        });
    }

    /**
     * 点顾客气泡触发提示动画
     * @param id 
     */
    public shakeTip(id: number) {
        this.groupNodes.forEach((o) => {
            o.getComponent(HospitalGroup).shakeTip(id);
        });
    }

    /** 暂存区是否为空 */
    private getTempIsNull() {
        const arr = this.hospitalData.tempData.filter((o) => o === -1);
        return arr.length >= this.hospitalData.tempData.length;
    }

    /** 清空暂存 放回池子 */
    private cleanTempArea(name: string) {
        for (let i = 0; i < this.hospitalData.tempData.length; i++) {
            const id = this.hospitalData.tempData[i];
            if (id != -1) {
                this.hospitalData.tempData[i] = -1;
                this.tempNodes[i].getComponent(HospitalIcon).setTempData({ tempId: i, itemId: -1 }, -1);
                // 第一关特殊处理，如果放到底层三格会被引导提示框挡住
                const num = this.hospitalData.cellData.length;
                const index = Math.floor(Math.random() * num);
                this.hospitalData.cellData[index].mids.push(id);
                this.refreshGroup(this.hospitalData.cellData[index].gid, this.hospitalData.cellData[index].col, false, name);
            }
        }
    }

    /** 整理格子 */
    private clearUp() {
        // AudioManager.instance.playSound(ESoundType.HospitalClearup);

        // 从整个池子中取物品id逻辑
        const arr: number[] = [];
        // 把池子中不为空的数据放进数组
        this.hospitalData.cellData.forEach((o) => {
            o.mids.forEach((o1) => {
                if (o1 != -1) arr.push(o1);
            });
        });
        // console.log("arr:", arr);
        arr.sort(() => Math.random() - 0.5);
        // console.log("打乱arr:", arr);

        let count = 0;
        this.hospitalData.cellData.forEach((o) => {
            if (o.mids.length > 0) {
                // console.log("改变前:", o.mids);
                for (let k = 0; k < o.mids.length; k++) {
                    if (o.mids[k] != -1) {
                        o.mids[k] = arr[count];
                        count++;
                        if (count >= arr.length) {
                            console.log("整理货柜完成~");
                        }
                    }
                }
                // console.log("改变后:", o.mids);
            }
        });

        // 重新创建
        this.groupNodes.forEach((o) => {
            o.destroy();
        });
        this.groupNodes = [];
        this.groupModule();

        // 播放整理动画
        this.block.active = true;
        this.zhengliSke.node.active = true;
        const data: IBaseSkeData = {
            ske: this.zhengliSke,
            animName: "zhengli",
            isLoop: false,
            callback: () => {
                this.zhengliSke.node.active = false;
                this.block.active = false;
            }
        };
        GameUtil.playAnimation(data);
    }

    /** 直接取货 */
    private guestGo(isAuto: boolean = false) {
        const guests: IHospitalGuestData[] = [];
        for (let i = 0; i < this.hospitalData.guestData.length; i++) {
            const guest = this.guestNodes[i].getComponent(HospitolGuest);
            // 非移动中&已解锁
            if (!guest.getIsMove() && this.hospitalData.guestData[i].itemId != -1) {
                guests.push(this.hospitalData.guestData[i]);
            }
        }
        if (guests.length <= 0) {
            // console.log("游客不存在:", guests);
            return;
        }

        // 顾客中随机一个直接走
        const index = Math.floor(Math.random() * guests.length);
        const guest = guests[index];
        const cellIds: number[] = [];
        for (let i = 0; i < this.hospitalData.cellData.length; i++) {
            const cell = this.hospitalData.cellData[i];
            for (let k = cell.curDeep; k < cell.mids.length; k++) {
                if (guest.itemId === cell.mids[k]) {
                    cellIds.push(cell.id);
                }
            }
        }

        if (cellIds.length <= 0) {
            return;
        }

        // 含有id的池子中取(顾客需求数-顾客已有数)个
        const ids = cellIds.sort(() => { return 0.5 - Math.random(); });
        const count = guest.max - guest.cur;
        if (count <= 0) return;
        if (!isAuto) {
            for (let i = 0; i < count; i++) {
                const cell = this.getCellDataById(ids[i]);
                if (cell) {
                    for (let k = cell.curDeep; k < cell.mids.length; k++) {
                        if (cell.mids[k] === guest.itemId) {
                            const from = this.groupNodes[cell.gid];
                            this.flyItemIcon(from, guest.itemId);
                            cell.mids.splice(k, 1);
                            this.refreshGroup(cell.gid, cell.col, false, '直接取货');
                            break;
                        }
                    }
                }
            }
        } else {
            const cell = this.getCellDataById(ids[0]);
            if (cell) {
                for (let k = cell.curDeep; k < cell.mids.length; k++) {
                    if (cell.mids[k] === guest.itemId) {
                        const from = this.groupNodes[cell.gid];
                        this.flyItemIcon(from, guest.itemId);
                        cell.mids.splice(k, 1);
                        this.refreshGroup(cell.gid, cell.col, false, '直接取货');
                        break;
                    }
                }
            }
        }
    }

    public checkGameFail() {
        if (this.isGameEnd) {
            return;
        }

        const arr = this.hospitalData.tempData.filter((o) => o != -1);
        if (arr.length >= TEMP_NUM) {
            this.isGameEnd = true;
            this.block.active = true;
            setTimeout(() => {
                this.block.active = false;
                this.showView(EViewName.Revive);
            }, 500);
            // console.log("游戏失败~");
        }
    }

    public checkGameSuccess() {
        if (this.isGameEnd) {
            return;
        }

        let isSuccess = true;
        if (this.groupNodes.length <= 0) {
            isSuccess = false;
        }

        for (let i = 0; i < this.groupNodes.length; i++) {
            const group = this.groupNodes[i];
            for (let k = 0; k < group.children.length; k++) {
                const node = group.children[k].children[1];
                if (node && node.active) {
                    isSuccess = false;
                    break;
                }
            }
        }

        for (let i = 0; i < this.hospitalData.tempData.length; i++) {
            if (this.hospitalData.tempData[i] != -1) {
                isSuccess = false;
                break;
            }
        }

        if (isSuccess) {
            // console.log("游戏过关~");
            this.hospitalData.cellData = [];
            this.hospitalData.guestData = [];
            this.hospitalData.tempData = [];
            this.initData();
        }
    }

    /**
     * 根据权重获取id
     * @returns 
     */
    private getSpeciesId() {
        let p = Math.random();
        let temp = 0;
        let total = 0;
        this.data.counts.forEach((o) => {
            total += o;
        });

        for (let i = 0; i < this.data.counts.length; i++) {
            temp += this.data.counts[i] / total;
            if (temp >= p) {
                this.data.counts[i]--;
                // console.log("随机index:", i);
                // console.log("数组:", this.data.counts);
                return i;
            }
        }
    }

    /**
     * 从整个池子中随机物品id
     * @returns 
     */
    private getItemIdByPool() {
        // 从整个池子中取物品id逻辑
        const arr = [];
        // 把池子中不为空的数据放进数组
        this.hospitalData.cellData.forEach((o) => {
            o.mids.forEach((o1) => {
                if (o1 != -1) arr.push(o1);
            });
        });
        // 把暂存区不为空的数据放进数组
        this.hospitalData.tempData.forEach((o) => {
            if (o != -1) {
                arr.push(o);
            }
        });
        // 排除已经展示的顾客需求
        if (this.hospitalData.guestData) {
            for (let i = arr.length - 1; i > -1; i--) {
                for (let k = 0; k < this.hospitalData.guestData.length; k++) {
                    if (this.hospitalData.guestData[k].itemId !== -1 && arr[i] === this.hospitalData.guestData[k].itemId) {
                        arr.splice(i, 1);
                    }
                }
            }
        }

        if (arr.length == 0) {
            return null;
        }

        const index = Math.floor(Math.random() * arr.length);
        return arr[index];
    }

    /**
     * 从表面取物品id
     * @returns 
     */
    public getItemIdBySurface() {
        const set = (key: number) => {
            let value = map.get(key);
            if (value) {
                value++;
                map.set(key, value);
            } else {
                map.set(key, 1);
            }
        }

        // 从表层取物品id逻辑
        // 表层出现的物品id计数
        const map: Map<number, number> = new Map();
        this.hospitalData.cellData.forEach((o) => {
            for (let k = o.curDeep; k < o.curDeep + 1; k++) {
                let key = o.mids[k];
                if (key != undefined) {
                    set && set(key);
                }
            }
        });
        this.hospitalData.tempData.forEach((o) => {
            if (o > -1) { set && set(o); }
        });
        // console.log(map);
        // 排除已经展示的顾客需求
        // map的value设置成0
        if (this.hospitalData.guestData) {
            for (let k = 0; k < this.hospitalData.guestData.length; k++) {
                const data = this.hospitalData.guestData[k];
                if (data.itemId !== -1) {
                    map.delete(data.itemId);
                }
            }
        }
        // console.log(map);
        // 根据value数量 从多到少排序
        const moreKeys = [];
        const lessKeys = [];
        const array = Array.from(map);
        array.sort((a, b) => { return b[1] - a[1] })
        for (let [key, value] of array) {
            // console.log(key + ' = ' + value);
            if (value >= 3) {
                moreKeys.push(key);
            } else {
                lessKeys.push(key);
            }
        }
        // // 从表面数量多的中取id
        // if (keys.length > 0) {
        //     const index = Math.floor(Math.random() * keys.length);
        //     return keys[index];
        // }

        // 把表层物品分成数量大于3和小于3的组
        // 概率满足: 从数量大于3的组中取id
        // 概率不满足: 从数量小于3的组中取id
        // 数组长度小于1时，从整个池子中取id
        // const testNode = cc.find('testNode', this.top);
        // const pEditBox = cc.find("pEditBox", testNode).getComponent(cc.EditBox);
        // const p = pEditBox.string == '' ? 100 : Number(pEditBox.string);
        const t = Math.random() * 100;
        if (t < this.upLevel.p) {
            if (moreKeys.length > 0) {
                const id = moreKeys[Math.floor(Math.random() * moreKeys.length)];
                // console.log("概率内->从表面随机id:", id);
                return id;
            } else {
                const id = this.getItemIdByPool();
                // console.log("概率内->从池中随机id:", id);
                return id;
            }
        } else {
            if (lessKeys.length > 0) {
                const id = lessKeys[Math.floor(Math.random() * lessKeys.length)];
                // console.log("概率外->从表面随机id:", id);
                return id;
            } else {
                const id = this.getItemIdByPool();
                // console.log("概率外->从池中随机id:", id);
                return id;
            }
        }

        // // 如果没有合适的，还用之前逻辑
        // const id = this.getItemIdByPool();
        // return id;
    }

    /**
     * 设置单元数据
     * @param id 
     * @param row 深度
     */
    private setItemData(id: number, row: number) {
        const data = {
            gid: Math.floor(id / this._data.col),
            id: id,
            col: id % this._data.col,
            curDeep: 0,
            mids: [],
        };
        for (let k = 0; k < row; k++) {
            data.mids.push(this.getSpeciesId());
        }
        this.hospitalData.cellData.push(data);
    }

    /**
     * 刷新组中对应位置item
     * @param gid 
     * @param col 
     */
    public refreshGroup(gid: number, col: number, isMove: boolean, logName: string = '') {
        const group = this.groupNodes[gid];
        if (group) {
            const cla = group.getComponent(HospitalGroup);
            cla.refresh(col, isMove);
        } else {
            console.log(`组${gid}不存在!!!`);
        }
    }

    public flyItemIcon(from: cc.Node, itemId: number) {
        let flyToTemp = () => {
            // 往暂存区域飞
            for (let i = 0; i < this.hospitalData.tempData.length; i++) {
                if (this.hospitalData.tempData[i] === -1) {
                    this.hospitalData.tempData[i] = itemId;
                    let cb = () => {
                        this.tempNodes[i].getComponent(HospitalIcon).setTempData({ tempId: i, itemId: this.hospitalData.tempData[i] }, -1);
                        // 结束检测
                        this.checkGameFail();
                    }

                    if (from) {
                        this.addItemIcon(from, this.tempNodes[i], EFlyType.Item, itemId, cb);
                    } else {
                        cb && cb();
                        cb = null;
                    }
                    break;
                }
            }
        }

        const pos = this.getGuestPosByItemId(itemId);
        if (pos != -1) {
            const guest = this.guestNodes[pos].getComponent(HospitolGuest);
            // 往顾客位置飞
            if (!guest.getIsMove()) {
                const to = guest.getFlyToNode();
                if (to) {
                    this.addItemIcon(from, to, EFlyType.Item, itemId, () => {
                        guest.refreshUI();
                    });
                    // this.refreshGroup(cellData.gid, cellData.col, itemId);
                } else {
                    flyToTemp();
                }
            } else {
                flyToTemp();
            }
        } else {
            flyToTemp();
        }

        flyToTemp = null;
    }

    public refreshProgress(isadd: boolean = false) {
        if (this.hospitalData.id > 6) this.hospitalData.id = 6;
        const config = GlobalData.getHospitalConfig(this.hospitalData.id);
        if (isadd) {
            this.hospitalData.cur++;
            // 结束检测
            this.checkGameSuccess();
        }

        const bar = cc.find("progress", this.proNode).getComponent(cc.ProgressBar);
        const lab1 = cc.find("lab1", this.proNode).getComponent(cc.Label);
        const lab2 = cc.find("lab2", this.proNode).getComponent(cc.Label);
        const pro = this.hospitalData.cur / config.need;
        bar.progress = pro;
        lab1.string = `升级进度${Math.floor(pro * 100)}%`;
        lab2.string = `${this.hospitalData.cur}/${config.need}`;
        if (this.hospitalData.cur >= config.need) {
            if (this.hospitalData.id >= 6) {
                lab1.string = `已满级`;
                this.hospitalData.cur = this.hospitalData.cur > config.need ? config.need : this.hospitalData.cur;
                lab2.string = `${this.hospitalData.cur}/${config.need}`;
            }
            // 升级按钮
            this.btnUpgrade.active = true;
        }
        // 锤子
        this.btnChuizi.active = this.hospitalData.id / 2 >= this.hospitalData.groupLv && this.hospitalData.groupLv < 3;
    }

    private titleUp() {
        AudioManager.instance.playSound('医馆头衔升级');
        const config = GlobalData.getHospitalConfig(this.hospitalData.id);
        this.hospitalData.cur -= config.need;
        this.hospitalData.id++;
        this.setTitle();
        this.refreshProgress();
        this.updateTeacher();
        console.log("称号晋升~");
    }

    private addItemIcon(from: cc.Node, to: cc.Node, type: EFlyType, itemId: number, cb?: Function) {
        const scale = SceneGame.instance.getRootScale();
        const temp = this.flyItem.children[type];
        const node = cc.instantiate(temp);
        node.parent = this.flyItem;
        const fly = () => {
            const cover1 = GameUtil.convetOtherNodeSpaceAR(from, this.flyItem);
            const cover2 = GameUtil.convetOtherNodeSpaceAR(to, this.flyItem);
            node.setPosition(cc.v2(cover1.x, cover1.y));
            node.active = true;
            // 拖尾缩放
            const streak = cc.find("streak", node).getComponent(cc.MotionStreak);
            if (streak) {
                streak.stroke = streak.stroke * scale;
            }

            node.stopAllActions();
            cc.tween(node).sequence(
                cc.moveTo(0.35, cc.v2(cc.v2(cover2.x, cover2.y))),
                cc.callFunc(() => {
                    node.destroy();
                    cb && cb();
                    cb = null;
                }),
            ).start();
        }

        const sprite = cc.find("sprite", node).getComponent(cc.Sprite);
        this.setItemIcon(EItemType.Fly, itemId, sprite, 70, 120, fly);
    }

    public setItemIcon(type: EItemType, itemId: number, sprite: cc.Sprite, maxWidth: number, maxHeight: number, cb?: Function) {
        sprite.spriteFrame = null;
        if (itemId < 0 || itemId == null) {
            return;
        }

        const realId = Number(HospitalUI.instance.data.ids[itemId]);
        LoadUtil.instance.setSpriteFrame(sprite, EResType.HospitalItem, realId, maxWidth, maxHeight);
        cb && cb();
        cb = null;
    }

    public onCloseClicked() {
        super.onCloseClicked();
        AudioManager.instance.playMusic(EMusicType.TownBgm, 0.8);
        // 记录现在退出时间
        this.hospitalData.exitTime = Date.now();
        // 更新
        TownUI.instance.check();
        GameUI.instance.check();
    }

    private time: number = 0;
    protected update(dt: number) {
        const leftTime = this.hospitalData.autoEndTime - Date.now();
        this.labAutoTime.node.active = false;
        if (leftTime > 0) {
            this.time += dt;
            if (this.time >= 1) {
                this.time = 0;
                this.guestGo(true);
            }
        }

        // 倒计时
        this.countAutoTime();
    }

    private isClick: boolean = true;
    private onBtnClicked(event: cc.Event, data: cc.Event.EventCustom) {
        const name = event.target.name;
        switch (name) {
            case "btnStop":
                {
                    this.showView(EViewName.Pause);
                }
                break;
            case "btnClearUp":
                {
                    // 播放视频
                    AdManager.showVideoAd(() => {
                        this.clearUp();
                    });
                }
                break;
            case "btnPickup":
                {
                    // 播放视频
                    AdManager.showVideoAd(() => {
                        this.guestGo();
                    });
                }
                break;
            case "btnClean":
                {
                    if (this.getTempIsNull()) {
                        console.log("没有需要清理的格子~");
                        return;
                    }

                    // 播放视频
                    AdManager.showVideoAd(() => {
                        this.cleanTempArea('清理格子');
                    });
                }
                break;
            case "btnAuto":
                {
                    if (this.hospitalData.autoEndTime > Date.now()) {
                        console.log("还有时间");
                        return;
                    }

                    // 播放视频
                    AdManager.showVideoAd(() => {
                        if (this.hospitalData.autoEndTime < Date.now()) {
                            this.hospitalData.autoEndTime = Date.now();
                        }
                        this.hospitalData.autoEndTime += this.autoTime.add * 1000;
                    });
                }
                break;
            case "btnUpgrade":
                {
                    this.btnUpgrade.active = false;
                    this.titleUp();
                    this.updateTeacher();
                }
                break;
            case "btnChuizi":
                {
                    this.block.active = true;
                    this.guitaiSke.node.active = true;
                    const data: IBaseSkeData = {
                        ske: this.guitaiSke,
                        animName: "xiu",
                        isLoop: true,
                        loopCount: 5,
                        callback: () => {
                            this.btnChuizi.active = false;
                            this.hospitalData.groupLv++;
                            this.upgradeGuiTai();
                            this.refreshProgress();

                            // 修好动画
                            const data1: IBaseSkeData = {
                                ske: this.guitaiSke,
                                animName: "xiuhao",
                                isLoop: false,
                                callback: () => {
                                    this.block.active = false;
                                }
                            };
                            GameUtil.playAnimation(data1);
                        }
                    };
                    GameUtil.playAnimation(data);
                    
                    
                }
                break;
        }
        // console.log("onBtnClicked()===>按钮:", name);
    }

    // 弹窗按钮事件
    private onViewClicked(event: cc.Event, data: cc.Event.EventCustom) {
        let backFun = () => {
            // AdManager.exitLv(DATA.name);
            this.hospitalData.cellData = [];
            this.hospitalData.guestData = [];
            this.hospitalData.tempData = [];
            this.onCloseClicked();
        }

        let restart = () => {
            this.hospitalData.cellData = [];
            this.hospitalData.guestData = [];
            this.hospitalData.tempData = [];
            this.initData();
        }

        const name = event.target.name;
        switch (name) {
            case "btnBack":     // 返回主页按钮
                {
                    if (this.curView === EViewName.Pause) {
                        // AdManager.exitLv(DATA.name);
                        this.onCloseClicked();
                    } else {
                        backFun && backFun();
                    }
                }
                break;
            case "btnClose":    // 弹窗关闭按钮
                {
                    if (this.curView === EViewName.Revive) {    // 复活关闭===>失败页面
                        this.hideView(() => {
                            this.showView(EViewName.Fail);
                        })
                    } else if (this.curView === EViewName.Fail || this.curView === EViewName.Success) {// 成功|失败页面===>清数据&&关闭
                        backFun && backFun();
                    } else {
                        this.hideView();
                    }
                }
                break;
            case "btnRevive":   // 复活
                {
                    this.isGameEnd = false;
                    this.cleanTempArea('复活');
                    this.hideView();
                    // if (!this.isClick) {
                    //     return;
                    // }
                    // this.isClick = false;
                    // AdManager.reportVideo(EVideoType.Revive, DATA.id, DATA.name);
                    // AdManager.showVideoAd(() => {
                    //     this.isClick = true;
                    //     AdManager.reportOverVideo(DATA.id, DATA.name);
                    //     this.isGameEnd = false;
                    //     this.cleanTempArea('复活');
                    //     this.hideView();
                    // }, () => {
                    //     this.isClick = true;
                    // })
                }
                break;
            case "btnRestart":  // 重新开始
            case "btnNext":     // 下一关
                {
                    restart && restart();
                }
                break;
        }
        backFun = null;
        restart = null;
        // console.log("onReviveClicked()===>按钮:", name);
    }



    private showView(type: EViewName) {
        this.curView = type;
        this.view.active = true;
        const mask = cc.find("mask", this.view);
        const root = cc.find("root", this.view);
        if (mask && root) {
            mask.opacity = 0;
            root.scale = 0;
            cc.tween(mask).to(0.3, { opacity: 180 }).start();
            cc.tween(root).to(0.3, { opacity: 255, scale: 1 }, cc.easeBackOut()).start();
            // 过关页面没有关闭按钮
            const btnClose = cc.find("btnClose", root);
            btnClose.active = this.curView != EViewName.Success;
        }

        const bg = cc.find("bg", root);
        bg.children.forEach((o) => {
            o.active = o.name == type;
        });

        switch (type) {
            case EViewName.Success:
                {
                    AudioManager.instance.playSound(ESoundType.HospitalSuccess);
                }
                break;
            case EViewName.Fail:
                {
                    AudioManager.instance.playSound(ESoundType.HospitalFail);
                }
                break;
        }
    }

    private hideView(cb?: Function) {
        const mask = cc.find("mask", this.view);
        const root = cc.find("root", this.view);
        if (mask) {
            cc.tween(mask).to(0.3, { opacity: 50 }).start();
        }

        if (root) {
            cc.tween(root).sequence(
                cc.spawn(
                    cc.scaleTo(0.3, 0.4).easing(cc.easeBackIn()),
                    cc.fadeOut(0.3),
                ),
                cc.callFunc(() => {
                    this.view.active = false;
                    this.curView = EViewName.Null;
                    cb && cb();
                    cb = null;
                }),
            ).start();
        }
    }


    /**
     * 根据物品id获取顾客节点
     * @param itemId 
     * @returns 
     */
    public getGuestPosByItemId(itemId: number) {
        for (let i = 0; i < this.hospitalData.guestData.length; i++) {
            const guest = this.hospitalData.guestData[i];
            if (guest.itemId === itemId) {
                return i;
            }
        }
        return -1;
    }

    public getGuestDataByItemId(itemId: number) {
        for (let i = 0; i < this.hospitalData.guestData.length; i++) {
            const guest = this.hospitalData.guestData[i];
            if (guest.itemId === itemId) {
                return guest;
            }
        }
        return null;
    }


    /**
     * 根据组gid获取数据
     * @param gid 
     * @returns
     */
    public getItemDataByGid(gid: number) {
        const data = this.hospitalData.cellData.filter((o) => o.gid === gid);
        return data;
    }

    public getCellDataById(id: number) {
        const data = this.hospitalData.cellData.find((o) => o.id === id);
        return data;
    }

    public getGuestDataById(id: number) {
        const data = this.hospitalData.guestData[id];//.find((o) => o.id === id);
        return data;
    }

    public getGuestDatas() {
        return this.hospitalData.guestData;
    }

    /**
     * 局部坐标转世界坐标
     * @param node 
     * @returns 
     */
    private localToGlobal(node: cc.Node) {
        const pos = node.convertToWorldSpaceAR(cc.v2(0, 0));
        return pos;
    }

    public getColorByState(isUnlock: boolean) {
        return isUnlock ? '#FFFFFF' : '#8E8B8B';
    }
}
AppService.instance.registViewData(VIEW_DATA);